//@author A0099223B

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;

public class TaskTableManager {

	private static final int TABLE_VIEWPORT_HEIGHT = 300;
	private static final int TABLE_VIEWPORT_WIDTH = 500;

	private static final Color COLOR_BLACK = new Color(25, 25, 25);
	private static final Color COLOR_GREEN = new Color(60, 200, 150);

	private static final String DISPLAY_LABEL_FORMAT = "Displaying - %1$s";
	private static final String LABEL_NOT_DONE_FRAGMENT = " [Incomplete Tasks Only] ";
	private static final String LABEL_DONE_FRAGMENT = " [Done Tasks Only] ";
	private static final String LABEL_DESCRIPTION_FRAGMENT = " Description: %1$s ";
	private static final String LABEL_PROJECT_FRAGEMENT = " Project: %1$s ";
	private static final String LABEL_PLACE_FRAGMENT = " Place: %1$s ";
	private static final String LABEL_START_TIME_FRAGMENT = " Start Time: %1$s ";
	private static final String LABEL_END_TIME_FRAGMENT = " End Time: %1$s ";
	private static final String LABEL_TITLE_FRAGMENT = " Title: %1$s ";
	private static final String LABEL_KEYWORD_FRAGMENT = " Keyword: %1$s ";
	private static final String LABEL_ALL_TASKS = "All tasks";

	private static final String DISPLAYED_TIME_FORMAT = "dd/MM/yyyy HH:mm";

	private static final String MESSAGE_NO = "No";
	private static final String MESSAGE_YES = "Yes";

	private static final String[] COLUMN_NAMES = { "ID", "Title", "Start Time",
			"End Time", "Place", "Project", "Done", "Description" };

	private static final int COLUMN_NAMES_ARRAY_INDEX_ID = 0;
	private static final int COLUMN_NAMES_ARRAY_INDEX_TITLE = 1;
	private static final int COLUMN_NAMES_ARRAY_INDEX_START_TIME = 2;
	private static final int COLUMN_NAMES_ARRAY_INDEX_END_TIME = 3;
	private static final int COLUMN_NAMES_ARRAY_INDEX_PLACE = 4;
	private static final int COLUMN_NAMES_ARRAY_INDEX_PROJECT = 5;
	private static final int COLUMN_NAMES_ARRAY_INDEX_DONE = 6;
	private static final int COLUMN_NAMES_ARRAY_INDEX_DESCRIPTION = 7;
	
	private static final String EMPTY_STRING = "";

	private static JPanel taskTablePanel = null;
	private static JTable taskTable = new JTable();
	private static JLabel display = new JLabel(String.format(
			DISPLAY_LABEL_FORMAT, ""));

	public static JPanel getTablePanel() {
		if (taskTablePanel == null) {
			initialiseTablePanel();
		}
		assert (taskTable != null);
		return taskTablePanel;
	}

	public static void refresh(ArrayList<Task> listOfTasks,
			ListCommand lastListCommand) {
		refreshLabel(lastListCommand);
		refreshTable(listOfTasks);

	}

	private static void initialiseTablePanel() {
		configureTable();
		configureLabel();
		setPanelLayout();
		setComponents();
	}

	private static void configureTable() {
		taskTable = new JTable();
		taskTable.setModel(createTableModel());
		taskTable.getTableHeader().setReorderingAllowed(false);
		taskTable.getColumnModel().getColumn(COLUMN_NAMES_ARRAY_INDEX_DONE)
				.setCellRenderer(getColouredCellRenderer());
		taskTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
		taskTable.setPreferredScrollableViewportSize(new Dimension(
				TABLE_VIEWPORT_WIDTH, TABLE_VIEWPORT_HEIGHT));
		taskTable.setFillsViewportHeight(true);
	}

	private static TableCellRenderer getColouredCellRenderer() {
		return new DefaultTableCellRenderer() {
			@Override
			public Component getTableCellRendererComponent(JTable table,
					Object value, boolean isSelected, boolean hasFocus,
					int row, int col) {

				JLabel cellLabel = (JLabel) super
						.getTableCellRendererComponent(table, value,
								isSelected, hasFocus, row, col);
				setFontProperties(cellLabel);

				TableModel tableModel = table.getModel();

				setBackgroundBasedOnValue(row, col, cellLabel, tableModel);

				return cellLabel;

			}

			private void setFontProperties(JLabel l) {
				// Font colour
				l.setForeground(Color.WHITE);

				Font f = l.getFont();
				Font boldFont = new Font(f.getFontName(), Font.BOLD,
						f.getSize());
				l.setFont(boldFont);
			}

			private void setBackgroundBasedOnValue(int row, int col,
					JLabel cellLabel, TableModel tableModel) {

				if (((String) tableModel.getValueAt(row, col))
						.equalsIgnoreCase(MESSAGE_YES)) {
					cellLabel.setBackground(COLOR_GREEN);

				} else {
					cellLabel.setBackground(COLOR_BLACK);

				}
			}
		};

	}

	private static TableModel createTableModel() {
		return new DefaultTableModel(COLUMN_NAMES, 0) {
			@Override
			public boolean isCellEditable(int row, int column) {
				// all cells false
				return false;
			}
		};
	}

	private static void configureLabel() {
		display.setAlignmentX(Component.RIGHT_ALIGNMENT);
	}

	private static void setPanelLayout() {
		taskTablePanel = new JPanel();
		taskTablePanel
				.setLayout(new BoxLayout(taskTablePanel, BoxLayout.Y_AXIS));

	}

	private static void setComponents() {
		taskTablePanel.add(new JScrollPane(taskTable));
		taskTablePanel.add(display);

	}

	private static void refreshTable(ArrayList<Task> listOfTask) {
		((DefaultTableModel) taskTable.getModel()).setRowCount(0);

		for (Task task : listOfTask) {
			String[] data = taskToStringArray(task);
			((DefaultTableModel) taskTable.getModel()).addRow(data);
		}

	}

	private static String[] taskToStringArray(Task task) {
		String[] data = new String[8];
		data[COLUMN_NAMES_ARRAY_INDEX_ID] = Integer.toString(task.id);
		data[COLUMN_NAMES_ARRAY_INDEX_TITLE] = task.title;
		data[COLUMN_NAMES_ARRAY_INDEX_START_TIME] = obtainStartTime(task);
		data[COLUMN_NAMES_ARRAY_INDEX_END_TIME] = obtainEndTime(task);
		data[COLUMN_NAMES_ARRAY_INDEX_PLACE] = obtainPlace(task);
		data[COLUMN_NAMES_ARRAY_INDEX_PROJECT] = obtainProject(task);
		data[COLUMN_NAMES_ARRAY_INDEX_DONE] = obtainDoneState(task);
		data[COLUMN_NAMES_ARRAY_INDEX_DESCRIPTION] = obtainDescription(task);

		return data;
	}

	private static String obtainStartTime(Task task) {
		if (task.startTime != Task.EMPTY_TIME) {
			return getFormattedTime(task.startTime);
		}

		return EMPTY_STRING;
	}

	private static String obtainEndTime(Task task) {
		if (task.endTime != Task.EMPTY_TIME) {
			return getFormattedTime(task.endTime);
		}

		return EMPTY_STRING;
	}

	private static String obtainPlace(Task task) {
		if (task.place != Task.EMPTY_STRING) {
			return task.place;
		}

		return EMPTY_STRING;
	}

	private static String obtainProject(Task task) {
		if (task.project != Task.EMPTY_STRING) {
			return task.project;
		}

		return EMPTY_STRING;
	}

	private static String obtainDoneState(Task task) {
		if (task.isDone) {
			return MESSAGE_YES;
		} else {
			return MESSAGE_NO;
		}

	}

	private static String obtainDescription(Task task) {
		if (task.description != Task.EMPTY_STRING) {
			return task.description;
		}
		return EMPTY_STRING;
	}

	private static void refreshLabel(ListCommand lastListCommand) {
		if (lastListCommand.isListAll) {
			setLabelToAll(lastListCommand);
		} else {
			setLabelToCommandVariables(lastListCommand);
		}

	}

	private static void setLabelToCommandVariables(ListCommand lastListCommand) {
		String displayFilters = "";
		displayFilters += obtainDoneStateFilter(lastListCommand);
		displayFilters += obtainKeywordFilter(lastListCommand);
		displayFilters += obtainTitleFilter(lastListCommand);
		displayFilters += obtainStartTimeFilter(lastListCommand);
		displayFilters += obtainEndTimeFilter(lastListCommand);
		displayFilters += obtainPlaceFilter(lastListCommand);
		displayFilters += obtainProjectFilter(lastListCommand);
		displayFilters += obtainDescriptionFilter(lastListCommand);

		display.setText(String.format(DISPLAY_LABEL_FORMAT, displayFilters));
	}

	private static String obtainDoneStateFilter(ListCommand lastListCommand) {
		if (lastListCommand.displayDoneStates == ListCommand.DisplayDoneState.DONE) {
			return LABEL_DONE_FRAGMENT;
		} else if (lastListCommand.displayDoneStates == ListCommand.DisplayDoneState.NOTDONE) {
			return LABEL_NOT_DONE_FRAGMENT;
		}
		return EMPTY_STRING;
	}

	private static String obtainKeywordFilter(ListCommand lastListCommand) {
		if (lastListCommand.keyWordSearch != Task.EMPTY_STRING) {
			return String.format(LABEL_KEYWORD_FRAGMENT,
					lastListCommand.keyWordSearch);
		}
		return EMPTY_STRING;
	}

	private static String obtainTitleFilter(ListCommand lastListCommand) {
		if (lastListCommand.titleFilter != Task.EMPTY_STRING) {
			return String.format(LABEL_TITLE_FRAGMENT,
					lastListCommand.titleFilter);
		}
		return EMPTY_STRING;
	}

	private static String obtainStartTimeFilter(ListCommand lastListCommand) {
		if (lastListCommand.startTimeFilter != Task.EMPTY_TIME) {
			return String.format(LABEL_START_TIME_FRAGMENT,
					getFormattedTime(lastListCommand.startTimeFilter));
		}
		return EMPTY_STRING;
	}

	private static String obtainEndTimeFilter(ListCommand lastListCommand) {
		if (lastListCommand.endTimeFilter != Task.EMPTY_TIME) {
			return String.format(LABEL_END_TIME_FRAGMENT,
					getFormattedTime(lastListCommand.endTimeFilter));
		}
		return EMPTY_STRING;
	}

	private static String obtainPlaceFilter(ListCommand lastListCommand) {
		if (lastListCommand.placeFilter != Task.EMPTY_STRING) {
			return String.format(LABEL_PLACE_FRAGMENT,
					lastListCommand.placeFilter);
		}
		return EMPTY_STRING;
	}

	private static String obtainDescriptionFilter(ListCommand lastListCommand) {
		if (lastListCommand.descriptionFilter != Task.EMPTY_STRING) {
			return String.format(LABEL_DESCRIPTION_FRAGMENT,
					lastListCommand.descriptionFilter);
		}
		return EMPTY_STRING;
	}

	private static String obtainProjectFilter(ListCommand lastListCommand) {
		if (lastListCommand.projectFilter != Task.EMPTY_STRING) {
			return String.format(LABEL_PROJECT_FRAGEMENT,
					lastListCommand.projectFilter);
		}
		return EMPTY_STRING;
	}

	private static String getFormattedTime(Date time) {
		return new SimpleDateFormat(DISPLAYED_TIME_FORMAT).format(time);
	}

	private static void setLabelToAll(ListCommand lastListCommand) {
		String displayedSet = obtainDoneStateFilter(lastListCommand)
				+ LABEL_ALL_TASKS;
		display.setText(String.format(DISPLAY_LABEL_FORMAT, displayedSet));
	}
}
